package com.ficus.road.maintain.service;

import com.ficus.road.maintain.authority.vo.AllFactorEmergency;
import com.ficus.road.maintain.core.model.AllFactoryTypeEnum;
import com.ficus.road.maintain.core.model.Hit;
import com.ficus.road.maintain.core.model.PanelConfig;
import com.ficus.road.maintain.core.model.RoadTypeEnum;
import com.ficus.road.maintain.core.model.zh.BridgeInfo;
import com.ficus.road.maintain.core.model.zh.MileageStatistic;
import com.ficus.road.maintain.core.model.zh.OperationSign;
import com.ficus.road.maintain.dao.*;
import com.ficus.road.maintain.dao.xlj.XljWarningDao;
import com.ficus.road.maintain.util.FormatUtil;
import com.ficus.road.maintain.util.MyDateUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author xiawen yang
 * @date 2021/9/9 下午2:34
 */
@Component
public class PanelService {

    private final static String Tree_Fall_Down = "PIC_TREE_DISEASE_RESULT_DISEASE_FALL_DOWN";
    private final static String Fence_Fall_Down = "PIC_FENCE_DISEASE_RESULT_DISEASE_FALL_DOWN";
    @Autowired
    private XljWarningDao xljWarningDao;
    @Autowired
    private HitDao hitDao;
    @Autowired
    private HitAllFactoryDao hitAllFactoryDao;
    @Autowired
    private PanelDao panelDao;
    @Autowired
    private BridgeHotelWarningDao bridgeHotelWarningDao;
    @Autowired
    private MechanicalCleaningDao mechanicalCleaningDao;
    @Autowired
    private OperationSignDao operationSignDao;
    @Autowired
    private BridgeInfoService bridgeInfoService;
    @Autowired
    private BridgeInfoDao bridgeInfoDao;
    @Autowired
    private MileageInfoDao mileageInfoDao;

    public AllFactorEmergency queryEmergencyIndicator() {
        AllFactorEmergency allFactorEmergency = new AllFactorEmergency();
        Date today = new Date();
        Date firstDayOfMonth = MyDateUtil.getFirstDayOfMonth();
        Query queryXljWarning = new Query(Criteria.where("create_time").gte(firstDayOfMonth));
        int xljWarningCount = (int) xljWarningDao.count(queryXljWarning);
        int treeFallCount = getHitByType(Tree_Fall_Down, firstDayOfMonth, today);
        int fenceFallCount = getHitByType(Fence_Fall_Down, firstDayOfMonth, today);
//        int bridgeHotelWarningCount = (int) bridgeHotelWarningDao.count(new Query(Criteria.where("warning_time").gte(MyDateUtil.getFirstDayOfMonth())));
        allFactorEmergency.setXlj(xljWarningCount);
        allFactorEmergency.setTreeFall(treeFallCount);
        allFactorEmergency.setFenceFall(fenceFallCount);
//        allFactorEmergency.setBridgeHotel(bridgeHotelWarningCount);
        // 全要素治理数量统计
        String firstDayOfMonthStr = MyDateUtil.dateFormatStr(firstDayOfMonth, "yyyy-MM-dd");
        Query queryMC = new Query(Criteria.where("is_ok").is("不合格").and("date").gte(firstDayOfMonthStr));
        long cleaning = mechanicalCleaningDao.count(queryMC);
        allFactorEmergency.setCleaning(cleaning);
        List<String> enumValueList = AllFactoryTypeEnum.getEnumValueList();
        Query queryAll = new Query(Criteria.where("type").in(enumValueList).and("first_hit_time").lte(today.getTime() / 1000).gte(firstDayOfMonth.getTime() / 1000));
        List<Hit> hits = hitAllFactoryDao.findByQuery(queryAll);
        Map<String, Long> groupingMap = hits.stream().collect(Collectors.groupingBy(Hit::getType, Collectors.counting()));
        allFactorEmergency.setOverload(groupingMap.getOrDefault(AllFactoryTypeEnum.OVERRUN_CAR.getType(), 0l));
        allFactorEmergency.setRoadIce(groupingMap.getOrDefault(AllFactoryTypeEnum.ROAD_ICE.getType(), 0l));
        allFactorEmergency.setBridgeHotel(groupingMap.getOrDefault(AllFactoryTypeEnum.BRIDGE_HOTEL.getType(), 0l));
        return allFactorEmergency;
    }

    public int getHitByType(String hitType, Date firstDate, Date lastDate) {
        Query query = new Query(Criteria.where("first_hit_time")
                .gte(firstDate.getTime() / 1000).lt(lastDate.getTime() / 1000).and("type").is(hitType));
        int count = (int) hitDao.count(query);
        return count;
    }

    public PanelConfig getPanelConfig() {
        List<PanelConfig> all = panelDao.findAll();
        PanelConfig panelConfig = all.get(0);
        Date today = new Date();
        String dateStr = MyDateUtil.dateFormatStr(today, "yyyy-MM-dd");
        OperationSign fetch = operationSignDao.fetch(dateStr);
        if (ObjectUtils.isEmpty(fetch)){
            fetch = operationSignDao.findLastOne();
        }
        if (ObjectUtils.isNotEmpty(fetch)) {
            panelConfig.setRoadIntactRate(FormatUtil.keepDecimalsOfK(fetch.getRoadIntactRate(), 2));
            panelConfig.setRoadCleaningRate(FormatUtil.keepDecimalsOfK(fetch.getRoadCleaningRate(), 2));
            panelConfig.setRoadCoverage(FormatUtil.keepDecimalsOfK(fetch.getRoadCoverage(), 2));
            panelConfig.setBridgeIntactRate(FormatUtil.keepDecimalsOfK(fetch.getBridgeIntactRate(), 2));
            panelConfig.setBridgeInspectionRate(FormatUtil.keepDecimalsOfK(fetch.getBridgeInspectionRate(), 2));
        }

        // 统计桥梁
        List<BridgeInfo> bridgeInfoList = bridgeInfoDao.findAll();
        double bridgeSize = bridgeInfoList.size();
        double highwaySize = bridgeInfoList.stream().filter(item -> RoadTypeEnum.HIGHWAY.equals(item.getRoadType())).collect(Collectors.toList()).size();
        double roadSize = bridgeInfoList.stream().filter(item -> RoadTypeEnum.DIRECT.equals(item.getRoadType())).collect(Collectors.toList()).size();
        panelConfig.setBridge(bridgeSize);
        panelConfig.setBridgeHighwayRate(FormatUtil.keepDecimalsOfK(highwaySize * 100 / bridgeSize, 0));
        panelConfig.setBridgeRoadRate(FormatUtil.keepDecimalsOfK(roadSize * 100 / bridgeSize, 0));

        // 统计里程
        MileageStatistic mileageStatistic = mileageInfoDao.findOne(new Query().with(new Sort(Sort.Direction.DESC, "_id")).skip(0).limit(1));
        double mileageLength = mileageStatistic.getDirect().getAnnual() + mileageStatistic.getRoad().getAnnual();
        panelConfig.setMileage(mileageLength);
        panelConfig.setMileageHighwayRate(FormatUtil.keepDecimalsOfK(mileageStatistic.getDirect().getAnnual() * 100 / mileageLength, 0));
        panelConfig.setMileageRoadRate(FormatUtil.keepDecimalsOfK(mileageStatistic.getRoad().getAnnual() * 100 / mileageLength, 0));
        return panelConfig;
    }

    public List<Hit> queryHits(Query query) {
        List<Hit> eventHitCommonDOS = hitAllFactoryDao.findByQuery(query);
        long currentTime = System.currentTimeMillis() / 1000;
        eventHitCommonDOS.forEach(item -> {
            Long dispatchTime = item.getDispatchTime();
            if (dispatchTime != null) {
                int discoverTime = (int) (currentTime - dispatchTime);
                Integer limitHour = item.getAttrs().getLimitHour();
                if (limitHour > 0) {
                    int restHour = limitHour - discoverTime / 3600;
                    item.getAttrs().setRestResolveHour(restHour);
                }
            }
        });
        return eventHitCommonDOS;
    }

    public int countHitAllFactory(Query query) {
        List<Hit> eventHitCommonDOS = hitAllFactoryDao.findByQuery(query);
        return eventHitCommonDOS.size();
    }
}
